/*
 * Copyright 2012-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.context.properties.bind;

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.context.properties.bind.Bindable.BindRestriction;
import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.context.properties.source.ConfigurationPropertyState;
import org.springframework.boot.convert.ApplicationConversionService;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.core.env.Environment;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.util.Assert;

/**
 * 一个容器对象，用于从一个或多个 {@link ConfigurationPropertySource} 中绑定对象。
 *
 * @author Phillip Webb
 * @author Madhura Bhave
 * @since 2.0.0
 */
public class Binder {

	private static final Set<Class<?>> NON_BEAN_CLASSES = Collections
			.unmodifiableSet(new HashSet<>(Arrays.asList(Object.class, Class.class)));

	private final Iterable<ConfigurationPropertySource> sources;

	private final PlaceholdersResolver placeholdersResolver;

	private final BindConverter bindConverter;

	private final BindHandler defaultBindHandler;

	private final List<DataObjectBinder> dataObjectBinders;

	/**
	 * 为指定的属性源创建一个新的 {@link Binder} 实例。
	 * 将使用 {@link DefaultFormattingConversionService} 进行所有类型转换。
	 *
	 * @param sources 用于绑定的属性源
	 */
	public Binder(ConfigurationPropertySource... sources) {
		this((sources != null) ? Arrays.asList(sources) : null, null, null, null);
	}

	/**
	 * 为指定的属性源创建一个新的 {@link Binder} 实例。
	 * 将使用 {@link DefaultFormattingConversionService} 进行所有类型转换。
	 *
	 * @param sources 用于绑定的属性源
	 */
	public Binder(Iterable<ConfigurationPropertySource> sources) {
		this(sources, null, null, null);
	}

	/**
	 * 为指定的属性源创建一个新的 {@link Binder} 实例。
	 *
	 * @param sources 用于绑定的属性源
	 * @param placeholdersResolver 用于解析属性占位符的策略
	 */
	public Binder(Iterable<ConfigurationPropertySource> sources, PlaceholdersResolver placeholdersResolver) {
		this(sources, placeholdersResolver, null, null);
	}

	/**
	 * 为指定的属性源创建一个新的 {@link Binder} 实例。
	 *
	 * @param sources 用于绑定的属性源
	 * @param placeholdersResolver 用于解析属性占位符的策略
	 * @param conversionService 用于值转换的转换服务（传入 {@code null} 则使用 {@link ApplicationConversionService}）
	 */
	public Binder(Iterable<ConfigurationPropertySource> sources, PlaceholdersResolver placeholdersResolver,
			ConversionService conversionService) {
		this(sources, placeholdersResolver, conversionService, null);
	}

	/**
	 * 为指定的属性源创建一个新的 {@link Binder} 实例。
	 *
	 * @param sources 用于绑定的属性源
	 * @param placeholdersResolver 用于解析属性占位符的策略
	 * @param conversionService 用于值转换的转换服务（传入 {@code null} 则使用 {@link ApplicationConversionService}）
	 * @param propertyEditorInitializer 用于配置属性编辑器的初始化器（可将其用于值转换，若不需要初始化可为 {@code null}）。
	 *                                   通常用于调用 {@link ConfigurableListableBeanFactory#copyRegisteredEditorsTo}。
	 */
	public Binder(Iterable<ConfigurationPropertySource> sources, PlaceholdersResolver placeholdersResolver,
			ConversionService conversionService, Consumer<PropertyEditorRegistry> propertyEditorInitializer) {
		this(sources, placeholdersResolver, conversionService, propertyEditorInitializer, null);
	}

	/**
	 * 为指定的属性源创建一个新的 {@link Binder} 实例。
	 *
	 * @param sources 用于绑定的属性源
	 * @param placeholdersResolver 用于解析属性占位符的策略
	 * @param conversionService 用于值转换的转换服务（传入 {@code null} 则使用 {@link ApplicationConversionService}）
	 * @param propertyEditorInitializer 用于配置属性编辑器的初始化器（可将其用于值转换，若不需要初始化可为 {@code null}）。
	 *                                   通常用于调用 {@link ConfigurableListableBeanFactory#copyRegisteredEditorsTo}。
	 * @param defaultBindHandler 绑定时未指定处理器时使用的默认绑定处理器
	 * @since 2.2.0
	 */
	public Binder(Iterable<ConfigurationPropertySource> sources, PlaceholdersResolver placeholdersResolver,
			ConversionService conversionService, Consumer<PropertyEditorRegistry> propertyEditorInitializer,
			BindHandler defaultBindHandler) {
		this(sources, placeholdersResolver, conversionService, propertyEditorInitializer, defaultBindHandler, null);
	}

	/**
	 * 为指定的属性源创建一个新的 {@link Binder} 实例。
	 *
	 * @param sources 用于绑定的属性源
	 * @param placeholdersResolver 用于解析属性占位符的策略
	 * @param conversionService 用于值转换的转换服务（传入 {@code null} 则使用 {@link ApplicationConversionService}）
	 * @param propertyEditorInitializer 用于配置属性编辑器的初始化器（可将其用于值转换，若不需要初始化可为 {@code null}）。
	 *                                   通常用于调用 {@link ConfigurableListableBeanFactory#copyRegisteredEditorsTo}。
	 * @param defaultBindHandler 绑定时未指定处理器时使用的默认绑定处理器
	 * @param constructorProvider 提供构造函数的提供器，用于在绑定时确定使用哪个构造函数
	 * @since 2.2.1
	 */
	public Binder(Iterable<ConfigurationPropertySource> sources, PlaceholdersResolver placeholdersResolver,
			ConversionService conversionService, Consumer<PropertyEditorRegistry> propertyEditorInitializer,
			BindHandler defaultBindHandler, BindConstructorProvider constructorProvider) {
		this(sources, placeholdersResolver,
				(conversionService != null) ? Collections.singletonList(conversionService)
						: (List<ConversionService>) null,
				propertyEditorInitializer, defaultBindHandler, constructorProvider);
	}

	/**
	 * 为指定的属性源创建一个新的 {@link Binder} 实例。
	 *
	 * @param sources 用于绑定的属性源
	 * @param placeholdersResolver 用于解析属性占位符的策略
	 * @param conversionServices 值转换服务列表（传入 {@code null} 则使用 {@link ApplicationConversionService}）
	 * @param propertyEditorInitializer 用于配置属性编辑器的初始化器（可用于值转换；若不需要初始化可为 {@code null}）。
	 *                                   通常用于调用 {@link ConfigurableListableBeanFactory#copyRegisteredEditorsTo}。
	 * @param defaultBindHandler 绑定时未指定处理器时使用的默认绑定处理器
	 * @param constructorProvider 提供绑定时使用的构造函数的提供器
	 * @since 2.5.0
	 */
	public Binder(Iterable<ConfigurationPropertySource> sources, PlaceholdersResolver placeholdersResolver,
			List<ConversionService> conversionServices, Consumer<PropertyEditorRegistry> propertyEditorInitializer,
			BindHandler defaultBindHandler, BindConstructorProvider constructorProvider) {
		Assert.notNull(sources, "Sources must not be null");
		for (ConfigurationPropertySource source : sources) {
			Assert.notNull(source, "Sources must not contain null elements");
		}
		this.sources = sources;
		this.placeholdersResolver = (placeholdersResolver != null) ? placeholdersResolver : PlaceholdersResolver.NONE;
		this.bindConverter = BindConverter.get(conversionServices, propertyEditorInitializer);
		this.defaultBindHandler = (defaultBindHandler != null) ? defaultBindHandler : BindHandler.DEFAULT;
		if (constructorProvider == null) {
			constructorProvider = BindConstructorProvider.DEFAULT;
		}
		ValueObjectBinder valueObjectBinder = new ValueObjectBinder(constructorProvider);
		JavaBeanBinder javaBeanBinder = JavaBeanBinder.INSTANCE;
		this.dataObjectBinders = Collections.unmodifiableList(Arrays.asList(valueObjectBinder, javaBeanBinder));
	}

	/**
	 * 使用此 Binder 的 {@link ConfigurationPropertySource 属性源} 绑定指定的目标 {@link Class}。
	 *
	 * @param name 要绑定的配置属性名称
	 * @param target 目标类
	 * @param <T> 绑定的类型
	 * @return 绑定结果（永不为 {@code null}）
	 * @see #bind(ConfigurationPropertyName, Bindable, BindHandler)
	 */
	public <T> BindResult<T> bind(String name, Class<T> target) {
		return bind(name, Bindable.of(target));
	}

	/**
	 * 使用此 Binder 的 {@link ConfigurationPropertySource 属性源} 绑定指定的 {@link Bindable} 目标。
	 *
	 * @param name 要绑定的配置属性名称
	 * @param target 要绑定的目标
	 * @param <T> 绑定的类型
	 * @return 绑定结果（永不为 {@code null}）
	 * @see #bind(ConfigurationPropertyName, Bindable, BindHandler)
	 */
	public <T> BindResult<T> bind(String name, Bindable<T> target) {
		return bind(ConfigurationPropertyName.of(name), target, null);
	}

	/**
	 * 使用此 Binder 的 {@link ConfigurationPropertySource 属性源} 绑定指定的 {@link Bindable} 目标。
	 *
	 * @param name 要绑定的配置属性名称
	 * @param target 要绑定的目标
	 * @param <T> 绑定的类型
	 * @return 绑定结果（永不为 {@code null}）
	 * @see #bind(ConfigurationPropertyName, Bindable, BindHandler)
	 */
	public <T> BindResult<T> bind(ConfigurationPropertyName name, Bindable<T> target) {
		return bind(name, target, null);
	}

	/**
	 * 使用此 Binder 的 {@link ConfigurationPropertySource 属性源} 绑定指定的 {@link Bindable} 目标。
	 *
	 * @param name 要绑定的配置属性名称
	 * @param target 要绑定的目标
	 * @param handler 绑定处理器（可以为 {@code null}）
	 * @param <T> 绑定的类型
	 * @return 绑定结果（永不为 {@code null}）
	 */
	public <T> BindResult<T> bind(String name, Bindable<T> target, BindHandler handler) {
		return bind(ConfigurationPropertyName.of(name), target, handler);
	}

	/**
	 * 使用此 Binder 的 {@link ConfigurationPropertySource 属性源} 绑定指定的 {@link Bindable} 目标。
	 *
	 * @param name 要绑定的配置属性名称
	 * @param target 要绑定的目标
	 * @param handler 绑定处理器（可以为 {@code null}）
	 * @param <T> 绑定的类型
	 * @return 绑定结果（永不为 {@code null}）
	 */
	public <T> BindResult<T> bind(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler) {
		T bound = bind(name, target, handler, false);
		return BindResult.of(bound);
	}

	/**
	 * 使用此 Binder 的 {@link ConfigurationPropertySource 属性源} 绑定指定的目标 {@link Class}，
	 * 如果绑定结果为 {@code null}，则使用 {@link Bindable} 的类型创建一个新实例。
	 *
	 * @param name 要绑定的配置属性名称
	 * @param target 目标类
	 * @param <T> 绑定的类型
	 * @return 绑定的对象或新创建的对象
	 * @since 2.2.0
	 * @see #bind(ConfigurationPropertyName, Bindable, BindHandler)
	 */
	public <T> T bindOrCreate(String name, Class<T> target) {
		return bindOrCreate(name, Bindable.of(target));
	}

	/**
	 * 使用此 Binder 的 {@link ConfigurationPropertySource 属性源} 绑定指定的 {@link Bindable} 目标，
	 * 如果绑定结果为 {@code null}，则使用 {@link Bindable} 的类型创建一个新实例。
	 *
	 * @param name 要绑定的配置属性名称
	 * @param target 要绑定的目标对象
	 * @param <T> 绑定的类型
	 * @return 绑定的对象或新创建的对象
	 * @since 2.2.0
	 * @see #bindOrCreate(ConfigurationPropertyName, Bindable, BindHandler)
	 */
	public <T> T bindOrCreate(String name, Bindable<T> target) {
		return bindOrCreate(ConfigurationPropertyName.of(name), target, null);
	}

	/**
	 * 使用此 Binder 的 {@link ConfigurationPropertySource 属性源} 绑定指定的 {@link Bindable} 目标，
	 * 如果绑定结果为 {@code null}，则使用 {@link Bindable} 的类型创建一个新实例。
	 *
	 * @param name 要绑定的配置属性名称
	 * @param target 要绑定的目标对象
	 * @param handler 绑定处理器
	 * @param <T> 绑定的类型
	 * @return 绑定的对象或新创建的对象
	 * @since 2.2.0
	 * @see #bindOrCreate(ConfigurationPropertyName, Bindable, BindHandler)
	 */
	public <T> T bindOrCreate(String name, Bindable<T> target, BindHandler handler) {
		return bindOrCreate(ConfigurationPropertyName.of(name), target, handler);
	}

	/**
	 * 使用此 Binder 的 {@link ConfigurationPropertySource 属性源} 绑定指定的 {@link Bindable} 目标，
	 * 如果绑定结果为 {@code null}，则使用 {@link Bindable} 的类型创建一个新实例。
	 *
	 * @param name 要绑定的配置属性名称
	 * @param target 要绑定的目标对象
	 * @param handler 绑定处理器（可以为 {@code null}）
	 * @param <T> 绑定或创建的对象类型
	 * @return 绑定的对象或新创建的对象
	 * @since 2.2.0
	 */
	public <T> T bindOrCreate(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler) {
		return bind(name, target, handler, true);
	}

	private <T> T bind(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler, boolean create) {
		Assert.notNull(name, "Name must not be null");
		Assert.notNull(target, "Target must not be null");
		handler = (handler != null) ? handler : this.defaultBindHandler;
		Context context = new Context();
		return bind(name, target, handler, context, false, create);
	}

	private <T> T bind(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler, Context context,
			boolean allowRecursiveBinding, boolean create) {
		try {
			// 开始阶段，获取被替换的目标对象
			Bindable<T> replacementTarget = handler.onStart(name, target, context);
			if (replacementTarget == null) {
				// 没有替换对象，直接绑定
				return handleBindResult(name, target, handler, context, null, create);
			}
			// 替换目标对象
			target = replacementTarget;
			// 绑定对象
			Object bound = bindObject(name, target, handler, context, allowRecursiveBinding);
			// 处理绑定结果
			return handleBindResult(name, target, handler, context, bound, create);
		}
		catch (Exception ex) {
			// 处理绑定失败逻辑
			return handleBindError(name, target, handler, context, ex);
		}
	}

	private <T> T handleBindResult(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler,
			Context context, Object result, boolean create) throws Exception {
		if (result != null) {
			// 绑定结果不为空，进入成功阶段
			result = handler.onSuccess(name, target, context, result);
			// 转换为目标类型
			result = context.getConverter().convert(result, target);
		}
		if (result == null && create) {
			// 如果绑定结果为空，且
			result = create(target, context);
			result = handler.onCreate(name, target, context, result);
			result = context.getConverter().convert(result, target);
			Assert.state(result != null, () -> "Unable to create instance for " + target.getType());
		}
		handler.onFinish(name, target, context, result);
		return context.getConverter().convert(result, target);
	}

	private Object create(Bindable<?> target, Context context) {
		for (DataObjectBinder dataObjectBinder : this.dataObjectBinders) {
			Object instance = dataObjectBinder.create(target, context);
			if (instance != null) {
				return instance;
			}
		}
		return null;
	}

	private <T> T handleBindError(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler,
			Context context, Exception error) {
		try {
			Object result = handler.onFailure(name, target, context, error);
			return context.getConverter().convert(result, target);
		}
		catch (Exception ex) {
			if (ex instanceof BindException) {
				throw (BindException) ex;
			}
			throw new BindException(name, target, context.getConfigurationProperty(), ex);
		}
	}

	private <T> Object bindObject(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler,
			Context context, boolean allowRecursiveBinding) {
		ConfigurationProperty property = findProperty(name, target, context);
		if (property == null && context.depth != 0 && containsNoDescendantOf(context.getSources(), name)) {
			return null;
		}
		AggregateBinder<?> aggregateBinder = getAggregateBinder(target, context);
		if (aggregateBinder != null) {
			return bindAggregate(name, target, handler, context, aggregateBinder);
		}
		if (property != null) {
			try {
				return bindProperty(target, context, property);
			}
			catch (ConverterNotFoundException ex) {
				// 我们仍然可以使用递归绑定器绑定它
				Object instance = bindDataObject(name, target, handler, context, allowRecursiveBinding);
				if (instance != null) {
					return instance;
				}
				throw ex;
			}
		}
		return bindDataObject(name, target, handler, context, allowRecursiveBinding);
	}

	private AggregateBinder<?> getAggregateBinder(Bindable<?> target, Context context) {
		Class<?> resolvedType = target.getType().resolve(Object.class);
		if (Map.class.isAssignableFrom(resolvedType)) {
			return new MapBinder(context);
		}
		if (Collection.class.isAssignableFrom(resolvedType)) {
			return new CollectionBinder(context);
		}
		if (target.getType().isArray()) {
			return new ArrayBinder(context);
		}
		return null;
	}

	private <T> Object bindAggregate(ConfigurationPropertyName name, Bindable<T> target, BindHandler handler,
			Context context, AggregateBinder<?> aggregateBinder) {
		AggregateElementBinder elementBinder = (itemName, itemTarget, source) -> {
			boolean allowRecursiveBinding = aggregateBinder.isAllowRecursiveBinding(source);
			Supplier<?> supplier = () -> bind(itemName, itemTarget, handler, context, allowRecursiveBinding, false);
			return context.withSource(source, supplier);
		};
		return context.withIncreasedDepth(() -> aggregateBinder.bind(name, target, elementBinder));
	}

	private <T> ConfigurationProperty findProperty(ConfigurationPropertyName name, Bindable<T> target,
			Context context) {
		if (name.isEmpty() || target.hasBindRestriction(BindRestriction.NO_DIRECT_PROPERTY)) {
			return null;
		}
		for (ConfigurationPropertySource source : context.getSources()) {
			ConfigurationProperty property = source.getConfigurationProperty(name);
			if (property != null) {
				return property;
			}
		}
		return null;
	}

	private <T> Object bindProperty(Bindable<T> target, Context context, ConfigurationProperty property) {
		context.setConfigurationProperty(property);
		Object result = property.getValue();
		result = this.placeholdersResolver.resolvePlaceholders(result);
		result = context.getConverter().convert(result, target);
		return result;
	}

	private Object bindDataObject(ConfigurationPropertyName name, Bindable<?> target, BindHandler handler,
			Context context, boolean allowRecursiveBinding) {
		if (isUnbindableBean(name, target, context)) {
			return null;
		}
		Class<?> type = target.getType().resolve(Object.class);
		if (!allowRecursiveBinding && context.isBindingDataObject(type)) {
			return null;
		}
		DataObjectPropertyBinder propertyBinder = (propertyName, propertyTarget) -> bind(name.append(propertyName),
				propertyTarget, handler, context, false, false);
		return context.withDataObject(type, () -> {
			for (DataObjectBinder dataObjectBinder : this.dataObjectBinders) {
				Object instance = dataObjectBinder.bind(name, target, context, propertyBinder);
				if (instance != null) {
					return instance;
				}
			}
			return null;
		});
	}

	private boolean isUnbindableBean(ConfigurationPropertyName name, Bindable<?> target, Context context) {
		for (ConfigurationPropertySource source : context.getSources()) {
			if (source.containsDescendantOf(name) == ConfigurationPropertyState.PRESENT) {
				// 我们知道有属性绑定，所以我们不能绕过任何东西
				return false;
			}
		}
		Class<?> resolved = target.getType().resolve(Object.class);
		if (resolved.isPrimitive() || NON_BEAN_CLASSES.contains(resolved)) {
			return true;
		}
		return resolved.getName().startsWith("java.");
	}

	private boolean containsNoDescendantOf(Iterable<ConfigurationPropertySource> sources,
			ConfigurationPropertyName name) {
		for (ConfigurationPropertySource source : sources) {
			if (source.containsDescendantOf(name) != ConfigurationPropertyState.ABSENT) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 从指定的 environment 创建一个新的 {@link Binder} 实例。
	 *
	 * @param environment 环境来源（必须附带 {@link ConfigurationPropertySources}）
	 * @return 一个 {@link Binder} 实例
	 */
	public static Binder get(Environment environment) {
		return get(environment, null);
	}

	/**
	 * 从指定的 environment 创建一个新的 {@link Binder} 实例。
	 *
	 * @param environment 环境来源（必须附带 {@link ConfigurationPropertySources}）
	 * @param defaultBindHandler 如果在绑定时未指定处理器，将使用的默认绑定处理器
	 * @return 一个 {@link Binder} 实例
	 * @since 2.2.0
	 */
	public static Binder get(Environment environment, BindHandler defaultBindHandler) {
		// 获取配置属性源迭代器
		Iterable<ConfigurationPropertySource> sources = ConfigurationPropertySources.get(environment);
		// 创建属性源占位符解析器
		PropertySourcesPlaceholdersResolver placeholdersResolver = new PropertySourcesPlaceholdersResolver(environment);
		// 将上面的属性包装成绑定器
		return new Binder(sources, placeholdersResolver, null, null, defaultBindHandler);
	}

	/**
	 * 绑定时使用的上下文对象，同时也是 {@link BindContext} 的实现类。
	 */
	final class Context implements BindContext {

		private int depth;

		private final List<ConfigurationPropertySource> source = Arrays.asList((ConfigurationPropertySource) null);

		private int sourcePushCount;

		private final Deque<Class<?>> dataObjectBindings = new ArrayDeque<>();

		private final Deque<Class<?>> constructorBindings = new ArrayDeque<>();

		private ConfigurationProperty configurationProperty;

		private void increaseDepth() {
			this.depth++;
		}

		private void decreaseDepth() {
			this.depth--;
		}

		private <T> T withSource(ConfigurationPropertySource source, Supplier<T> supplier) {
			if (source == null) {
				return supplier.get();
			}
			this.source.set(0, source);
			this.sourcePushCount++;
			try {
				return supplier.get();
			}
			finally {
				this.sourcePushCount--;
			}
		}

		private <T> T withDataObject(Class<?> type, Supplier<T> supplier) {
			this.dataObjectBindings.push(type);
			try {
				return withIncreasedDepth(supplier);
			}
			finally {
				this.dataObjectBindings.pop();
			}
		}

		private boolean isBindingDataObject(Class<?> type) {
			return this.dataObjectBindings.contains(type);
		}

		private <T> T withIncreasedDepth(Supplier<T> supplier) {
			increaseDepth();
			try {
				return supplier.get();
			}
			finally {
				decreaseDepth();
			}
		}

		void setConfigurationProperty(ConfigurationProperty configurationProperty) {
			this.configurationProperty = configurationProperty;
		}

		void clearConfigurationProperty() {
			this.configurationProperty = null;
		}

		void pushConstructorBoundTypes(Class<?> value) {
			this.constructorBindings.push(value);
		}

		boolean isNestedConstructorBinding() {
			return !this.constructorBindings.isEmpty();
		}

		void popConstructorBoundTypes() {
			this.constructorBindings.pop();
		}

		PlaceholdersResolver getPlaceholdersResolver() {
			return Binder.this.placeholdersResolver;
		}

		BindConverter getConverter() {
			return Binder.this.bindConverter;
		}

		@Override
		public Binder getBinder() {
			return Binder.this;
		}

		@Override
		public int getDepth() {
			return this.depth;
		}

		@Override
		public Iterable<ConfigurationPropertySource> getSources() {
			if (this.sourcePushCount > 0) {
				return this.source;
			}
			return Binder.this.sources;
		}

		@Override
		public ConfigurationProperty getConfigurationProperty() {
			return this.configurationProperty;
		}

	}

}
